package io.gitee.zhangbinhub.admin.oauth.service

import com.mybatisflex.core.query.QueryWrapper
import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.admin.oauth.base.OauthBaseService
import io.gitee.zhangbinhub.admin.oauth.entity.ModuleFunc
import io.gitee.zhangbinhub.admin.oauth.entity.RoleModuleFunc
import io.gitee.zhangbinhub.admin.oauth.entity.User
import io.gitee.zhangbinhub.admin.oauth.po.ModuleFuncPo
import io.gitee.zhangbinhub.admin.oauth.repo.ModuleFuncRepository
import io.gitee.zhangbinhub.admin.oauth.repo.RoleModuleFuncRepository
import io.gitee.zhangbinhub.admin.oauth.repo.RoleRepository
import io.gitee.zhangbinhub.admin.oauth.repo.UserRepository
import io.gitee.zhangbinhub.admin.oauth.vo.ModuleFuncVo
import org.noear.solon.annotation.Component
import org.noear.solon.annotation.Inject
import org.noear.solon.data.annotation.Transaction

@Component
open class ModuleFuncService(
    @Inject userRepository: UserRepository,
    private val roleRepository: RoleRepository,
    private val moduleFuncRepository: ModuleFuncRepository,
    private val roleModuleFuncRepository: RoleModuleFuncRepository
) : OauthBaseService(userRepository) {

    fun getAllModuleFuncList(): MutableList<ModuleFunc> =
        moduleFuncRepository.selectListByQuery(QueryWrapper.create().orderBy(ModuleFunc::code).asc()).let {
            val map: MutableMap<String, ModuleFunc> = mutableMapOf()
            it.forEach { item ->
                map[item.id] = item
            }
            sortModuleFuncList(formatToTreeList(map))
        }

    fun getModuleFuncList(userId: String): MutableList<ModuleFunc> =
        userRepository.selectOneWithRelationsById(userId).let {
            val moduleFuncIds: MutableSet<String> = mutableSetOf()
            it.roleSet.flatMap { item -> item.moduleFuncSet }
                .filter { item ->
                    if (moduleFuncIds.contains(item.id)) {
                        false
                    } else {
                        moduleFuncIds.add(item.id)
                        true
                    }
                }
                .toMutableList()
        }

    fun getModuleFuncList(appId: String, loginNo: String): MutableList<ModuleFunc> =
        (getUserInfoByLoginNo(loginNo) ?: throw WebException("无法获取当前用户信息")).let {
            val moduleFuncIds: MutableSet<String> = mutableSetOf()
            it.roleSet.asSequence().filter { role -> role.appId == appId }
                .flatMap { item -> item.moduleFuncSet }
                .filter { item ->
                    if (moduleFuncIds.contains(item.id)) {
                        false
                    } else {
                        moduleFuncIds.add(item.id)
                        true
                    }
                }
                .filter { menu -> menu.appId == appId }
                .toMutableList()
        }

    private fun sortModuleFuncList(moduleFuncList: MutableList<ModuleFunc>): MutableList<ModuleFunc> =
        moduleFuncList.let { list ->
            list.forEach { organization ->
                if (organization.children.isNotEmpty()) {
                    sortModuleFuncList(organization.children)
                }
            }
            moduleFuncList.apply {
                this.sortBy { it.code }
            }
        }

    fun getModuleFuncListByAppId(appId: String): List<ModuleFunc> =
        moduleFuncRepository.selectListByQuery(QueryWrapper.create().where(ModuleFunc::appId).eq(appId)).let {
            val map: MutableMap<String, ModuleFunc> = mutableMapOf()
            it.forEach { item ->
                map[item.id] = item
            }
            sortModuleFuncList(formatToTreeList(map))
        }

    @Throws(WebException::class)
    private fun doSave(userInfo: User, moduleFunc: ModuleFunc, moduleFuncPo: ModuleFuncPo): ModuleFunc =
        (if (moduleFuncPo.roleIds.isNotEmpty()) {
            roleRepository.selectListByIds(moduleFuncPo.roleIds)
        } else {
            mutableListOf()
        }).let { roleSetPo ->
            if (validateModifyRoleSet(userInfo, moduleFuncPo.appId!!, moduleFunc.roleSet, roleSetPo)) {
                moduleFunc.copy(
                    name = moduleFuncPo.name!!,
                    code = moduleFuncPo.code!!
                ).apply {
                    parentId = moduleFuncPo.parentId!!
                }.also {
                    moduleFuncRepository.insertOrUpdate(it)
                }.also {
                    roleModuleFuncRepository.deleteByQuery(
                        QueryWrapper.create().where(RoleModuleFunc::moduleId).eq(it.id)
                    )
                    if (moduleFuncPo.roleIds.isNotEmpty()) {
                        roleModuleFuncRepository.insertBatch(moduleFuncPo.roleIds.map { roleId ->
                            RoleModuleFunc(roleId = roleId, moduleId = it.id)
                        })
                    }
                }
            } else {
                throw WebException("不合法的操作，不允许修改更高级别的角色列表！")
            }
        }

    @Transaction
    @Throws(WebException::class)
    open fun doCreate(loginNo: String, moduleFuncPo: ModuleFuncPo): ModuleFunc =
        moduleFuncRepository.selectListByQuery(QueryWrapper.create().where(ModuleFunc::code).eq(moduleFuncPo.code!!))
            .let {
                if (it.isNotEmpty()) {
                    throw WebException("编码重复")
                }
                getUserInfoByLoginNo(loginNo)?.let { userInfo ->
                    doSave(
                        userInfo, ModuleFunc(
                            appId = moduleFuncPo.appId!!,
                            covert = true
                        ), moduleFuncPo
                    )
                } ?: throw WebException("无法获取当前用户信息")
            }

    @Transaction
    @Throws(WebException::class)
    open fun doDelete(idList: MutableList<String>) {
        moduleFuncRepository.selectListByQuery(QueryWrapper.create().where(ModuleFunc::getParentId).`in`(idList)).apply {
            if (this.isNotEmpty()) {
                throw WebException("存在下级模块功能，不允许删除")
            }
        }
        roleModuleFuncRepository.deleteByQuery(
            QueryWrapper.create().where(RoleModuleFunc::moduleId).`in`(idList)
        )
        moduleFuncRepository.deleteByQuery(
            QueryWrapper.create().where(ModuleFunc::id).`in`(idList).and(ModuleFunc::covert).eq(true)
        )
    }

    @Transaction
    @Throws(WebException::class)
    open fun doUpdate(loginNo: String, moduleFuncPo: ModuleFuncPo): ModuleFunc =
        moduleFuncRepository.selectListByQuery(
            QueryWrapper.create().where(ModuleFunc::code).eq(moduleFuncPo.code!!).and(ModuleFunc::id)
                .ne(moduleFuncPo.id!!)
        ).let {
            if (it.isNotEmpty()) {
                throw WebException("编码重复")
            }
            getUserInfoByLoginNo(loginNo)?.let { userInfo ->
                doSave(userInfo, moduleFuncRepository.selectOneWithRelationsById(moduleFuncPo.id!!), moduleFuncPo)
            } ?: throw WebException("无法获取当前用户信息")
        }

    @Throws(WebException::class)
    fun getModuleFuncInfo(moduleFuncId: String): ModuleFuncVo =
        moduleFuncRepository.selectOneWithRelationsById(moduleFuncId).let { item ->
            ModuleFuncVo(
                id = item.id,
                appId = item.appId,
                code = item.code,
                name = item.name,
                parentId = item.parentId,
                roleIds = item.roleSet.map { it.id }.toMutableList()
            )
        }

}
